/*
 Author: Ido Green  / plus.ly/greenido
 Date: April 2012
 Simple demo for Google I/O 2012 - to show the power of GAE and HTML5 client side MVC+APIs.

 TODO: 
 1. Offline - use: http://westcoastlogic.com/lawnchair/
 1.a. http://www.html5rocks.com/en/tutorials/flexbox/quick/ for flexbox goodness.
 1.b. some cool css3 spinners 

 2. Use GAE APIs for the 'beers'.
 
 3. Polish with some CSS3 spinners etc'.

 Misc:
 jslint browser: true 
 global _, jQuery, $, console, Backbone 
*/

var beer = {};
// The main beer stuff we are creating using backbone.js
(function($){
    beer.Drink = Backbone.Model.extend({
        defaults: {
            date: new Date(),
            type: '',
            price: '',
            comments: '',
            score: '',
            geoLocation: ''
        },
        
        set: function(attributes, options) {
            var aDate;
            if (attributes.date){
                //TODO future version - make sure date is valid format during input
                aDate = new Date(attributes.date);
                if ( Object.prototype.toString.call(aDate) === "[object Date]" && !isNaN(aDate.getTime()) ){
                    attributes.date = aDate;
                }
            }
            Backbone.Model.prototype.set.call(this, attributes, options);
        },
        
        dateInputType: function(){
            //https://github.com/jquery/jquery-mobile/issues/2755
            return beer.formatDate(this.get('date'), "yyyy-mm-dd");
        },
        
        displayDate: function(){
            return beer.formatDate(this.get('date'), "mm/dd/yyyy");
        },
        
        toJSON: function(){
            var json = Backbone.Model.prototype.toJSON.call(this);
            return _.extend(json, {dateInputType : this.dateInputType(), displayDate: this.displayDate()});
        }
    });
    
    beer.formatDate = function(date, formatString){
        var yyyy, month, mm, day, dd, formatedDate;
        
        if (date instanceof Date){
            yyyy = date.getFullYear();
            month = date.getMonth() + 1;
            mm = month < 10 ? "0" + month : month;
            day = date.getDate();
            dd = day < 10 ? "0" + day : day;
            
            formatedDate = formatString.replace(/yyyy/i, yyyy);
            formatedDate = formatedDate.replace(/mm/i, mm);
            formatedDate = formatedDate.replace(/dd/i, dd);
        } else {
            formatedDate = "";
        }
        return formatedDate;
    };
    
    beer.items = Backbone.Collection.extend({
        model: beer.Drink,
        url: "beer.json",
        comparator: function(drink){
            var date = new Date(drink.get('date'));
            return date.getTime();
        }
    });
    
    beer.DrinkListView = Backbone.View.extend({
        tagName: 'ul',
        id: 'drinks-list',
        attributes: {"data-role": 'listview',
                     "data-filter": 'true',
                     "data-filter-placeholder": 'Search beers...',
                     "data-filter-theme": 'e',
                     "data-theme": 'e'
                    },

        initialize: function() {
            this.collection.bind('add', this.render, this);
            this.collection.bind('change', this.changeItem, this);
            this.collection.bind('reset', this.render, this);
            this.template = _.template($('#drink-list-item-template').html());
        },
        
        render: function() {
            var container = this.options.viewContainer,
                drinks = this.collection,
                template = this.template,
                listView = $(this.el);
                
            container.empty();
            $(this.el).empty();
            drinks.each(function(drink){
                this.renderItem(drink);
            }, this);
            container.html($(this.el));
            container.trigger('create');
            return this;
        },
        
        renderItem: function(item) {
            var template = this.template,
                listView = $(this.el),
                renderedItem = template(item.toJSON()),
                $renderedItem = $(renderedItem);
                
            $renderedItem.jqmData('drinkId', item.get('id'));
            $renderedItem.bind('click', function(){
                //set the drink id on the page element for use in the details pagebeforeshow event
                $('#drink-details').jqmData('drinkId', $(this).jqmData('drinkId'));  //'this' represents the element being clicked
            });
            
            listView.append($renderedItem);
        },
        
        changeItem: function(item){
            this.collection.sort();
        }
    });
    
    beer.DrinkDetailsView = Backbone.View.extend({
        //since this template will render inside a div, we don't need to specify a tagname
        initialize: function() {
            this.template = _.template($('#drink-details-template').html());
        },
        
        render: function() {
            var container = this.options.viewContainer,
                drink = this.model,
                renderedContent = this.template(this.model.toJSON());
                
            container.html(renderedContent);
            container.trigger('create');
            return this;
        }
    });
    
    beer.DrinkFormView = Backbone.View.extend({
        //since this template will render inside a div, we don't need to specify a tagname, 
        // but we do want the fieldcontain
        attributes: {"data-role": 'fieldcontain'},
        
        initialize: function() {
            this.template = _.template($('#drink-form-template').html());
        },
        
        render: function() {
            var container = this.options.viewContainer,
                renderedContent = this.template(this.model.toJSON());
                
            container.html(renderedContent);
            container.trigger('create');
            return this;
        }
    });
    
    beer.initData = function(){
        beer.drinks = new beer.items();
        // use async false to have the app wait for data before rendering the list
        beer.drinks.fetch({async: false});  
    };

    beer.location = function(){
        
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(function(position) {
              beer.curLocation = position.coords;
              console.log ("cur Lat: "+ position.coords.latitude + " Long: "+ position.coords.longitude);
              // TODO - show on a map
              //document.getElementById("startLat").innerHTML = position.latitude;
              //document.getElementById("startLon").innerHTML = position.longitude;
            }, function(error) {
              console.error("Error occurred. The code: " + error.code);
              // error.code can be:
              //   0: unknown error
              //   1: permission denied
              //   2: position unavailable (error response from locaton provider)
              //   3: timed out
            });
        }
    }
    
}(jQuery));

$('#drinks').live('pageinit', function(event){
    var drinksListContainer = $('#drinks').find(":jqmData(role='content')"),
        drinksListView;
    beer.initData();
    beer.location();
    drinksListView = new beer.DrinkListView({collection: beer.drinks, viewContainer: drinksListContainer});
    drinksListView.render();
});

$(document).ready(function(){
    
    $('#add-button').live('click', function(){
        var drink = new beer.Drink(),
            drinkForm = $('#drink-form-form'),
            drinkFormView;
    
        //clear any existing id attribute from the form page
        $('#drink-details').jqmRemoveData('drinkId');
        drinkFormView = new beer.DrinkFormView({model: drink, viewContainer: drinkForm});
        drinkFormView.render();
    });

    $('#drink-details').live('pagebeforeshow', function(){
        console.log('drinkId: ' + $('#drink-details').jqmData('drinkId'));
        var drinksDetailsContainer = $('#drink-details').find(":jqmData(role='content')"),
            drinkDetailsView,
            drinkId = $('#drink-details').jqmData('drinkId'),
            drinkModel = beer.drinks.get(drinkId);
    
        drinkDetailsView = new beer.DrinkDetailsView({model: drinkModel, viewContainer: drinksDetailsContainer});
        drinkDetailsView.render();
    });

    $('#edit-drink-button').live('click', function() {
        var drinkId = $('#drink-details').jqmData('drinkId'),
            drinkModel = beer.drinks.get(drinkId),
            drinkForm = $('#drink-form-form'),
            drinkFormView;
        
        drinkFormView = new beer.DrinkFormView({model: drinkModel, viewContainer: drinkForm});
        drinkFormView.render();
    });
    
    $('#save-drink-button').live('click', function(){
        var drinkId = $('#drink-details').jqmData('drinkId'),
            drink,
            dateComponents,
            formJSON = $('#drink-form-form').formParams();
        
        //if we are on iOS and we have a date...convert it from yyyy-mm-dd back to mm/dd/yyyy
        //TODO future version - for non-iOS, we would need to validate the date is in the expected format (mm/dd/yyyy)
        if (formJSON.date && ((navigator.userAgent.indexOf('iPhone') >= 0 || navigator.userAgent.indexOf('iPad') >= 0)) ){
            dateComponents = formJSON.date.split("-");
            formJSON.date = dateComponents[1] + "/" + dateComponents[2] + "/" + dateComponents[0];
        }
        
        if (drinkId){
            //editing
            drink = beer.drinks.get(drinkId);
            drink.set(formJSON); //not calling save since we have no REST backend...save in memory
        }else{
            //new (since we have no REST backend, create a new model and add to collection to prevent Backbone making REST calls)
            drink = new beer.Drink(formJSON);
            drink.set({'id': new Date().getTime()});  //create some identifier
            beer.drinks.add(drink);
        }
    });
});

